#include "wxspropertycontainer.h"
#include "wxspropertygridmanager.h"

#include "wxsemptyproperty.h"
#include "wxslongproperty.h"
#include "wxsboolproperty.h"

#include <wx/msgdlg.h>
#include <globals.h>

long wxsPropertyContainer::Flags = 0;
bool wxsPropertyContainer::IsRead = false;
TiXmlElement* wxsPropertyContainer::CurrentElement = 0;
wxsPropertyStream* wxsPropertyContainer::CurrentStream = 0;
wxMutex wxsPropertyContainer::Mutex;

wxsPropertyContainer::wxsPropertyContainer():
  CurrentQP( 0 ),
  BlockChangeCallback( false ) {
}

wxsPropertyContainer::~wxsPropertyContainer() {
  if( wxsPGRID() ) {
    wxsPGRID()->UnbindPropertyContainer( this, false );
  }
  if( CurrentQP ) {
    CurrentQP->Container = 0;
    CurrentQP = 0;
  }
}

void wxsPropertyContainer::ShowInPropertyGrid() {
  wxMutexLocker Lock( Mutex );
  if( !wxsPGRID() ) {
    return;
  }
  Flags = ( GetPropertiesFlags() & ~( flXml | flPropStream ) ) | flPropGrid;
  wxsPGRID()->Freeze();
  wxsPGRID()->StoreSelected();
  wxsPGRID()->NewPropertyContainerStart();
  OnEnumProperties( Flags );
  wxsPGRID()->NewPropertyContainerFinish( this );
  Flags = 0;
  OnAddExtraProperties( wxsPGRID() );
  wxsPGRID()->Thaw();
  wxsPGRID()->RestoreSelected();
}

void wxsPropertyContainer::XmlRead( TiXmlElement* Element ) {
  wxMutexLocker Lock( Mutex );
  TiXmlNode::SetCondenseWhiteSpace( false );
  Flags = ( GetPropertiesFlags() & ~( flPropGrid | flPropStream ) ) | flXml;
  IsRead = true;
  CurrentElement = Element;
  OnEnumProperties( Flags );
  Flags = 0;
}

void wxsPropertyContainer::XmlWrite( TiXmlElement* Element ) {
  wxMutexLocker Lock( Mutex );
  TiXmlNode::SetCondenseWhiteSpace( false );
  Flags = ( GetPropertiesFlags() & ~( flPropGrid | flPropStream ) ) | flXml;
  IsRead = false;
  CurrentElement = Element;
  OnEnumProperties( Flags );
  Flags = 0;
}

void wxsPropertyContainer::PropStreamRead( wxsPropertyStream* Stream ) {
  wxMutexLocker Lock( Mutex );
  Flags = ( GetPropertiesFlags() & ~( flPropGrid | flXml ) ) | flPropStream;
  IsRead = true;
  CurrentStream = Stream;
  OnEnumProperties( Flags );
  NotifyPropertyChange( true );
  Flags = 0;
}

void wxsPropertyContainer::PropStreamWrite( wxsPropertyStream* Stream ) {
  wxMutexLocker Lock( Mutex );
  Flags = ( GetPropertiesFlags() & ~( flPropGrid | flXml ) ) | flPropStream;
  IsRead = false;
  CurrentStream = Stream;
  OnEnumProperties( Flags );
  NotifyPropertyChange( true );
  Flags = 0;
}

void wxsPropertyContainer::NotifyPropertyChangeFromPropertyGrid() {
  if( BlockChangeCallback ) {
    return;
  }
  BlockChangeCallback = true;
  if( CurrentQP ) {
    CurrentQP->Update();
  }
  OnPropertyChanged();
  BlockChangeCallback = false;
}

void wxsPropertyContainer::NotifyPropertyChangeFromQuickProps() {
  if( BlockChangeCallback ) {
    return;
  }
  BlockChangeCallback = true;
  if( wxsPGRID() ) {
    wxsPGRID()->Update( this );
  }
  OnPropertyChanged();
  BlockChangeCallback = false;
}

void wxsPropertyContainer::NotifyPropertyChange( bool CallPropertyChangeHandler ) {
  if( BlockChangeCallback ) {
    return;
  }
  BlockChangeCallback = true;
  if( CurrentQP ) {
    CurrentQP->Update();
  }
  if( wxsPGRID() ) {
    wxsPGRID()->Update( this );
  }
  if( CallPropertyChangeHandler ) {
    OnPropertyChanged();
  }
  BlockChangeCallback = false;
}

wxsQuickPropsPanel* wxsPropertyContainer::BuildQuickPropertiesPanel( wxWindow* Parent ) {
  if( CurrentQP ) {
    CurrentQP->Container = 0;
  }
  CurrentQP = OnCreateQuickProperties( Parent );
  return CurrentQP;
}

void wxsPropertyContainer::Property( wxsProperty& Prop ) {
  switch( Flags & ( flPropGrid | flXml | flPropStream ) ) {
    case flPropGrid:
      wxsPGRID()->NewPropertyContainerAddProperty( &Prop, this );
      break;
    case flXml:
      if( IsRead ) {
        Prop.XmlRead( this, CurrentElement->FirstChildElement( cbU2C( Prop.GetDataName() ) ) );
      } else {
        TiXmlElement* Element = CurrentElement->InsertEndChild(
                                  TiXmlElement( cbU2C( Prop.GetDataName() ) ) )->ToElement();
        if( !Prop.XmlWrite( this, Element ) ) {
          CurrentElement->RemoveChild( Element );
        }
      }
      break;
    case flPropStream:
      if( IsRead ) {
        Prop.PropStreamRead( this, CurrentStream );
      } else
      { Prop.PropStreamWrite( this, CurrentStream ); }
      break;
    default:
      wxMessageBox( _T( "wxsPropertyContainer::Property() function has been\n" )
                    _T( "called manually. If you are the Developer,\n" )
                    _T( "please remove this code." ) );
  }
}

void wxsPropertyContainer::SubContainer( wxsPropertyContainer* Container, long NewFlags ) {
  if( !Container ) {
    return;
  }
  long FlagsStore = Flags;
  Flags = ( Flags    & ( flPropGrid | flXml | flPropStream ) ) |
          ( NewFlags & ~( flPropGrid | flXml | flPropStream ) );
  Container->OnEnumProperties( NewFlags );
  Flags = FlagsStore;
}
